package com.kaifamiao.controller;

import com.kaifamiao.entity.Customer;
import com.kaifamiao.service.CustomerService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.tinylog.Logger;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@WebServlet("/customer/*")
public class CustomerServlet extends HttpServlet {

    private String ctxPath;
    private CustomerService customerService;

    @Override
    public void init() throws ServletException {
        customerService = new CustomerService();
        ctxPath = this.getServletContext().getContextPath();
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final String method = request.getMethod();
        final String uri = request.getRequestURI();
        Logger.trace("{} {}", method, uri);
        // 浏览器用GET方式访问以"/list"为后缀的路径
        if( "GET".equals( method ) && uri.endsWith("/list") ) {
            this.list(request, response);
            return;
        }
        // 浏览器用GET方式访问以"/add"为后缀的路径
        if( "GET".equals( method ) && uri.endsWith("/add") ) {
            this.addPage(request, response);
            return;
        }
        // 浏览器用POST方式访问以"/add"为后缀的路径
        if( "POST".equals( method ) && uri.endsWith("/add") ) {
            this.addAction(request, response);
            return;
        }
        // 浏览器用GET方式访问以"/remove"为后缀的路径
        if( "GET".equals( method ) && uri.endsWith("/remove") ) {
            this.remove(request, response);
            return;
        }
        // 浏览器用GET方式访问以"/edit"为后缀的路径
        if( "GET".equals( method ) && uri.endsWith("/edit") ) {
            this.editPage(request, response);
            return;
        }
        // 浏览器用POST方式访问以"/edit"为后缀的路径
        if( "POST".equals( method ) && uri.endsWith("/edit") ) {
            this.editAction(request, response);
            return;
        }
        // 浏览器用GET方式访问以"/change"为后缀的路径
        if( "GET".equals( method ) && uri.endsWith("/change") ) {
            this.changePage(request, response);
            return;
        }
        // 浏览器用POST方式访问以"/change"为后缀的路径
        if( "POST".equals( method ) && uri.endsWith("/change") ) {
            this.changeAction(request, response);
            return;
        }
    }

    private void list(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Logger.trace("查询用户列表");
        List<Customer> list= customerService.loadAll();
        request.setAttribute( "customers", list );
        String path = "/WEB-INF/customer/list.jsp";
        this.forward(path, request, response);
    }

    private void addPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Logger.trace("打开新用户添加页面");
        String path = "/WEB-INF/customer/add.jsp";
        this.forward(path, request, response);
    }

    private boolean validateAdd(HttpServletRequest request){
        HttpSession session = request.getSession();
        String username = request.getParameter("username");
        String nickname = request.getParameter("nickname");
        if(StringUtils.isEmpty(username)){
            session.setAttribute("message", "用户名不能为空");
            return false;
        }

        // 调用customerService中的方法检查 登录名称 是否已经被占用

        String password = request.getParameter("password");
        if(StringUtils.isEmpty(password)){
            session.setAttribute( "username", username );
            session.setAttribute( "nickname", nickname );
            session.setAttribute("message", "登录密码不能为空");
            return false;
        }
        String confirm = request.getParameter("confirm");
        if(!StringUtils.equals(password,confirm)){
            session.setAttribute("message", "两次密码输入不一致");
            return false;
        }
        return true;
    }

    private void addAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if( this.validateAdd(request) ) {
            // 接收用户提交的参数
            Map<String, String[]> map = request.getParameterMap();
            Customer c = new Customer();
            try {
                BeanUtils.populate(c, map);
            } catch (Exception e) {
                e.printStackTrace();
            }
            customerService.save(c);
            response.sendRedirect(ctxPath + "/customer/list");
            return;
        }
        response.sendRedirect( ctxPath + "/customer/add" );
    }

    private void remove(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final String url = ctxPath + "/customer/list";
        String id = request.getParameter("id");
        if( StringUtils.isEmpty(id) || StringUtils.isBlank(id) ) {
            HttpSession session = request.getSession();
            session.setAttribute("message","删除失败");
            response.sendRedirect(url);
            return;
        }

        Integer cid = Integer.valueOf(id);
        customerService.delete(cid);
        response.sendRedirect(url);
    }

    private void editPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final String url = ctxPath + "/customer/list";
        String id = request.getParameter("id");
        if( StringUtils.isEmpty(id) || StringUtils.isBlank(id) ) {
            HttpSession session = request.getSession();
            session.setAttribute("message","无法获取原始数据");
            response.sendRedirect(url);
            return;
        }
        Integer cid = Integer.valueOf(id);
        Customer c = customerService.load(cid);
        request.setAttribute("customer", c );
        String path = "/WEB-INF/customer/edit.jsp";
        this.forward(path, request, response);
    }

    private boolean validateEdit(HttpServletRequest request)
            throws ServletException, IOException {
        String id = request.getParameter("id");
        String username = request.getParameter("username");
        String nickname = request.getParameter("nickname");
        if(StringUtils.isEmpty(nickname) || StringUtils.isBlank(nickname)) {
            HttpSession session = request.getSession();
            session.setAttribute("id", id);
            session.setAttribute("username", username);
            session.setAttribute( "message", "请输入昵称" );
            return false;
        }
        return true;
    }

    private void editAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final String success = ctxPath + "/customer/list";
        String id = request.getParameter("id");
        String nickname = request.getParameter("nickname");
        if(this.validateEdit(request)){
            // 根据用户编号查询用户数据
            Customer c = customerService.load(Integer.valueOf(id));
            // 修改用户数据
            c.setNickname( nickname );
            // 更新用户信息
            customerService.update(c);
            HttpSession session = request.getSession();
            session.setAttribute("message", "修改成功" );
            response.sendRedirect(success);
            return;
        }
        response.sendRedirect(ctxPath + "/customer/edit?id=" + id);
    }

    private void changePage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id = request.getParameter("id");
        Integer cid = Integer.valueOf(id);
        Customer c = customerService.load(cid);
        request.setAttribute("customer", c );
        String path = "/WEB-INF/customer/change.jsp";
        this.forward(path, request, response);
    }

    private boolean validateChange(HttpServletRequest request) throws ServletException, IOException {
        String id = request.getParameter("id");
        String original = request.getParameter("original");
        String password = request.getParameter("password");
        String confirm = request.getParameter("confirm");
        HttpSession session = request.getSession();
        if(StringUtils.isEmpty(original) || StringUtils.isBlank(original)) {
            session.setAttribute("message", "必须输入原始密码");
            return false;
        }

        if(StringUtils.isEmpty(password) || StringUtils.isBlank(password)) {
            session.setAttribute("message", "请输入新密码");
            return false;
        }

        if( !StringUtils.equals(password,confirm) ) {
            session.setAttribute("message", "两次输入的新密码不一致");
            return false;
        }

        Customer c = customerService.load(Integer.valueOf(id));
        request.setAttribute("targetCustomer", c );
        // 对用户输入的原始密码进行加密
        String encrypted = customerService.encrypt(original, c.getSalt());
        // 对用户输入的原始密码加密后再与数据库中存储的密码比较
        if( !StringUtils.equals(encrypted, c.getPassword())) {
            session.setAttribute("message", "你输入的原始密码不正确");
            return false;
        }

        return true;
    }

    private void changeAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id = request.getParameter("id");
        if(Objects.isNull(id)) {
            response.sendRedirect(ctxPath + "/customer/list");
            return;
        }
        if(this.validateChange(request)){
            // 获得用户在表单中填写的原始密码
            final String password = request.getParameter("password");
            // 根据用户编号查询用户数据
            Customer c = (Customer)request.getAttribute("targetCustomer");
            // 对用户输入的密码进行加密
            String encrypted = customerService.encrypt(password, c.getSalt());
            // 修改用户数据
            c.setPassword(encrypted);
            // 更新用户信息
            customerService.update(c);
            response.sendRedirect(ctxPath + "/customer/list");
            return;
        }
        response.sendRedirect(ctxPath + "/customer/change?id=" + id);
    }

    private void forward(String path, HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

}
